package com.briup.day20;

public class SingletonTest {
    public static void main(String[] args) {
        /*
            单例指的是在整个程序中，保证某一个类只能存在唯一的一个对象；
            如果要保证对象唯一应该如何设计？
            创建对象的方式？
            通过构造器创建，只需要构造器私有化，能够保证对象无法在类外进行创建
         */
        /*Singleton singleton = new Singleton();
        System.out.println(singleton);
        Singleton singleton2 = new Singleton();
        System.out.println(singleton2);*/
        // 设置一个任务，用于获取单例对象
        Runnable task = () -> {
            try {
                System.out.println(Singleton.getInstance());
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        };
        for (int i = 0; i < 20; i++) {
            Thread t = new Thread(task);
            t.start();
        }
    }
}

class Singleton {
    // 3. 设置一个静态的类变量，用于维护本类唯一的对象
    private static Singleton singleton;

    // 1.单例第一步，构造器私有
    private Singleton() {
    }

    // 2.在类内部创建对象，通过方法的返回值返回
    // 在静态方法上添加 synchronized同步锁，锁对象为 当前类的字节码对象
    // 如果上了同步锁之后，当线程a获取到锁对象后操作本方法时，其他线程会进入到锁阻塞状态，
    // 保证了其他线程此时无法进入到本方法中，只有当线程a执行完本方法后，会释放锁对象，
    // 那其他线程才会短暂的从锁阻塞状态转换为可运行状态
    public static synchronized Singleton getInstance() throws InterruptedException {
        // 懒汉式实现 单例模式，先不创建单例对象，只有等你需要的实时在创建和维护该对象
        if (singleton == null) {
            Thread.sleep(3000);
            singleton = new Singleton();
        }
        return singleton;
    }
}
